package modulo4.model;

import java.io.FileWriter;
import java.io.IOException;
import java.nio.file.FileSystems;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

/**
 * @author jjsanche
 */
public class ConvertidorTablaHTMLToExcel {

    enum TableElement {

        TR("<TR.*?>.*?</TR>"), TD("<TD.*?>.*?</TD>");

        private final String regEx;

        private TableElement(String regEx) {
            this.regEx = regEx;
        }

        public String getRegEx() {
            return regEx;
        }
    }

    private String textoHTML;
    private String textoExcel;
    private Path archivoHTML;

    public static void main(String[] args) throws IOException {
        ConvertidorTablaHTMLToExcel c = new ConvertidorTablaHTMLToExcel(Paths.get("D:\\Google Drive\\Escuela Mr. Computer\\table.html"));
        c.convertir();
        c.guardarArchivoHTML();
    }

    public ConvertidorTablaHTMLToExcel(String texto) {
        textoHTML = texto;
    }

    public ConvertidorTablaHTMLToExcel(Path archivo) throws IOException {
        textoHTML = new String(Files.readAllBytes(archivo));
        archivoHTML = archivo;
    }

    public boolean convertir() {
        final int COL_SPAN = 0;
        final int ROW_SPAN = 1;

        String textoTabla = getTable();
        List<String> trs = getTs(textoTabla, TableElement.TR);
        StringBuilder aTextToExcel = new StringBuilder();
        List<String> colRow = new ArrayList<>();
        colRow.add("col");
        colRow.add("row");
        int colRowCount[] = new int[2];
        Map<Integer, Object> indexColRowSpans = new HashMap<>();
        int colIndex;
        
        for (int row = 0; row < trs.size(); row++) {
            colIndex = 0;
            
            List<String> tds = getTs(trs.get(row), TableElement.TD);

            Pattern textoPattern = Pattern.compile("<td(\\s(col|row)(span=)['\"](\\d)['\"])?.*?(\\s(?!\\2)(col|row)(\\3)['\"](\\d)['\"])?.*?>(.*?)</td>", Pattern.CASE_INSENSITIVE | Pattern.DOTALL);
            for (int col = 0; col < tds.size(); col++) {
                Matcher textoMatcher = textoPattern.matcher(tds.get(col));
                textoMatcher.find();

                int savedColRowSpans[] = (int[]) indexColRowSpans.get(colIndex);

                if (savedColRowSpans != null) {
                    do {
                        if (savedColRowSpans[ROW_SPAN]-- > 0) {
                            int colSpan = savedColRowSpans[COL_SPAN];
                            
                            if (savedColRowSpans[ROW_SPAN] <= 0) {
                                indexColRowSpans.put(colIndex, null);
                            }
                            
                            do {
                                aTextToExcel.append(',');
                                colIndex++;
                            } while (-- colSpan > 0);
                        }
                        
                        savedColRowSpans = (int[]) indexColRowSpans.get(colIndex);
                    } while (savedColRowSpans != null && savedColRowSpans[ROW_SPAN] > 0);
                }

                if (textoMatcher.group(2) != null) {
                    int aSpan = Integer.parseInt(textoMatcher.group(4));
                    colRowCount = new int[2];

                    colRowCount[colRow.indexOf(textoMatcher.group(2))] = aSpan;

                    if (textoMatcher.group(6) != null) {
                        aSpan = Integer.parseInt(textoMatcher.group(8));
                        colRowCount[colRow.indexOf(textoMatcher.group(6))] = aSpan;
                    }
                }
                
                if (colRowCount[ROW_SPAN] > 0) {
                    colRowCount[ROW_SPAN] --;
                }

                if (colRowCount[ROW_SPAN] > 0) {
                    indexColRowSpans.put(colIndex, colRowCount);
                }
                
                aTextToExcel.append(textoMatcher.group(9));
                aTextToExcel.append(',');
                colIndex++;
                
                if (colRowCount[COL_SPAN] > 1) {
                    int colSpan = colRowCount[COL_SPAN];
                    while (colSpan -- > 1) {
                        aTextToExcel.append(',');
                        colIndex ++;
                    }
                }
                
            }

            aTextToExcel.append('\n');
        }

        aTextToExcel.delete(aTextToExcel.length() - 1, aTextToExcel.length());

        textoExcel = aTextToExcel.toString();
        System.out.println(aTextToExcel);
        
        return false;
    }

    private String getTable() {
        Pattern tablePattern = Pattern.compile("<TABLE.*</TABLE>", Pattern.CASE_INSENSITIVE | Pattern.DOTALL);
        Matcher tableMatcher = tablePattern.matcher(textoHTML);
        tableMatcher.find();

        return tableMatcher.group();
    }

    private List<String> getTs(String texto, TableElement element) {
        Pattern trPattern = Pattern.compile(element.getRegEx(), Pattern.CASE_INSENSITIVE | Pattern.DOTALL);
        Matcher trMatcher = trPattern.matcher(texto);
        List<String> trsList = new ArrayList<>();

        while (trMatcher.find()) {
            trsList.add(trMatcher.group());
        }

        return trsList;
    }

    public void guardarArchivoHTML(String path) throws IOException {
        try (FileWriter archivoExcel = new FileWriter(path);) {
            archivoExcel.append(textoExcel);
            archivoExcel.flush();
        }
    }
    
    public void guardarArchivoHTML() throws IOException {
        String htmlFile = this.archivoHTML.getFileName().toString();
        String htmlRegularExpression = "(?i).+?\\.HTML?";
        StringBuilder csvFile = new StringBuilder();
        
        if (htmlFile.matches(htmlRegularExpression)) {
            csvFile.append(this.archivoHTML.getRoot());
            csvFile.append(this.archivoHTML.subpath(0, this.archivoHTML.getNameCount() - 1).toString());
            csvFile.append(FileSystems.getDefault().getSeparator());
            csvFile.append(htmlFile.split("(?i)\\.HTML?")[0]);
            csvFile.append(".csv");
        } else {
            csvFile.append(this.archivoHTML.toString());
            csvFile.append(".csv");
        }
        
        System.out.println(csvFile);
        
            guardarArchivoHTML(csvFile.toString());
    }

    public void getErrores() {

    }

    public void setPathArchivoHTML(Path archivo) throws IOException {
        textoHTML = new String(Files.readAllBytes(archivo));
    }

    public void setPathArchivoExcel() {

    }

    public void getPathArchivoExcel() {

    }

    public Path getPathArchivoHTML() {
        return archivoHTML;
    }
}